#include <gtest/gtest.h>
#include <sqlite_orm/sqlite_orm.h>

#include <memory>
#include <string>
#include <vector>

#include "common_utils.hpp"

// 定义一个简单的用户结构体用于测试
struct User {
    int id;
    std::string name;
    int age;
    std::string email;

    // 相等运算符，用于测试比较
    bool operator==(const User& other) const {
        return id == other.id && name == other.name && age == other.age &&
               email == other.email;
    }
};

// 测试固件类
class SQLiteTest : public ::testing::Test {
   protected:
    // 数据库连接和 ORM 配置
    using Storage = decltype(sqlite_orm::make_storage(
        "test.db",
        sqlite_orm::make_table(
            "users",
            sqlite_orm::make_column("id", &User::id, sqlite_orm::primary_key()),
            sqlite_orm::make_column("name", &User::name),
            sqlite_orm::make_column("age", &User::age),
            sqlite_orm::make_column("email", &User::email))));

    std::unique_ptr<Storage> storage;

    void SetUp() override {
        // 创建内存数据库，用于测试
        storage = std::make_unique<Storage>(sqlite_orm::make_storage(
            ":memory:", sqlite_orm::make_table(
                            "users",
                            sqlite_orm::make_column("id", &User::id,
                                                    sqlite_orm::primary_key()),
                            sqlite_orm::make_column("name", &User::name),
                            sqlite_orm::make_column("age", &User::age),
                            sqlite_orm::make_column("email", &User::email))));

        // 创建表
        storage->sync_schema();
    }

    void TearDown() override {
        // 删除表并关闭数据库连接
        if (storage) {
            storage->remove_all<User>();
            storage.reset();
        }
    }
};

// 测试用例：插入与读取
TEST_F(SQLiteTest, InsertAndRetrieve) {
    // 创建测试用户
    User user{0, "张三", 30, "zhangsan@example.com"};

    // 插入数据
    auto userId = storage->insert(user);

    // 验证ID已经被正确设置
    EXPECT_GT(userId, 0);

    // 读取数据
    auto retrievedUser = storage->get<User>(userId);

    // 验证读取的数据是否正确
    EXPECT_EQ(retrievedUser.name, "张三");
    EXPECT_EQ(retrievedUser.age, 30);
    EXPECT_EQ(retrievedUser.email, "zhangsan@example.com");
}

// 测试用例：更新数据
TEST_F(SQLiteTest, Update) {
    // 插入初始数据
    User user{0, "李四", 25, "lisi@example.com"};
    auto userId = storage->insert(user);

    // 修改数据
    User updatedUser{static_cast<int>(userId), "李四", 26,
                     "lisi_new@example.com"};
    storage->update(updatedUser);

    // 读取更新后的数据
    auto retrievedUser = storage->get<User>(userId);

    // 验证数据是否更新成功
    EXPECT_EQ(retrievedUser.age, 26);
    EXPECT_EQ(retrievedUser.email, "lisi_new@example.com");
}

// 测试用例：删除数据
TEST_F(SQLiteTest, Delete) {
    // 插入数据
    User user{0, "王五", 40, "wangwu@example.com"};
    auto userId = storage->insert(user);

    // 确认数据存在
    auto count = storage->count<User>();
    EXPECT_EQ(count, 1);

    // 删除数据
    storage->remove<User>(userId);

    // 验证数据已被删除
    count = storage->count<User>();
    EXPECT_EQ(count, 0);
}

// 测试用例：批量操作
TEST_F(SQLiteTest, BatchOperations) {
    // 准备测试数据
    std::vector<User> users = {{0, "张三", 30, "zhangsan@example.com"},
                               {0, "李四", 25, "lisi@example.com"},
                               {0, "王五", 40, "wangwu@example.com"}};

    // 批量插入
    for (auto& user : users) {
        storage->insert(user);
    }

    // 验证插入结果
    auto count = storage->count<User>();
    EXPECT_EQ(count, 3);

    // 使用查询获取所有年龄大于25的用户
    auto olderUsers = storage->get_all<User>(
        sqlite_orm::where(sqlite_orm::c(&User::age) > 25));
    EXPECT_EQ(olderUsers.size(), 2);
}